from random import randint

from django.contrib.auth import authenticate
from rest_framework import serializers
from rest_framework.authtoken.models import Token

from account.models import UserProfile
# from system.serializers import RoleSerializer
from system.models import Role


class RoleListSerializer(serializers.ModelSerializer):
    department = serializers.CharField(source="department.name")  # 部门名称
    position = serializers.CharField(source="position.name")  # 职位名称
    # 通过属性的属性
    is_leader = serializers.BooleanField(
        source="position.is_leader"
    )  # 是否为领导(不在role表中,在position表中)

    class Meta:
        model = Role
        fields = ["department", "position", "is_leader"]


class UserProfileSerializer(serializers.ModelSerializer):
    # token要从存放token的表中拿过来
    token = serializers.SerializerMethodField()
    # user是只读的
    user = serializers.SerializerMethodField()  # 字段:user_id
    # head_img = serializers.SerializerMethodField()
    # head_img_path = serializers.SerializerMethodField()  # 直接访问这个地址,可以正常显示图片

    # 展示的样式是序列化器控制的,数据是什么由model来控制的.
    role_list = RoleListSerializer(
        read_only=True, many=True, source="get_role_list"
    )  # 通过实例方法
    # role_list = RoleSerializer(read_only=True, many=True, source="get_role_list")  # 通过实例方法

    class Meta:
        model = UserProfile
        # fields = ("id", "review")  # 使用部分字段
        fields = "__all__"  # 使用全部字段

    # def get_head_img_path(self, obj):
    #     return f"/api/{obj.head_img}"

    # 更高效的实现方式(因为没有涉及到user表)
    def get_token(self, obj):  # obj是当前正在被序列化的模型实例
        user_id = obj.user_id  # 获取user_profile的user_id的值,假设是10
        token, is_created = Token.objects.get_or_create(
            user_id=user_id
        )  # token表中：创建或者是获取token中user_id为10的的token值
        return token.key

    # def get_token(self, obj):  # obj是当前正在被序列化的模型实例
    #     user = obj.user  # obj.user 是通过 Django 的外键关系访问 User 实例,这会触发一次额外的数据库查询,从 User 表中获取完整的 User 实例。
    #     token, is_created = Token.objects.get_or_create(user=user)
    #     return token.key

    def get_user(self, obj):
        return obj.user_id  # obj.user.id也是一样的


class LoginSerializer(
    serializers.Serializer
):  # serializers.Serializer是没有obj这个实例的
    username = serializers.CharField(required=True)  # 声明username的数据类型
    password = serializers.CharField(required=True)  # 声明password的数据类型

    # 校验单个字段,data就是接收到的字段的值
    def validate_username(self, data):
        # 校验字段
        return data

    def validate_password(self, data):
        # 校验字段
        return data

    def validate(self, attrs):  # attrs是字典   {"username": "xxx", "password": "yyy"}
        # 获取用户名和密码
        username = attrs["username"]
        password = attrs["password"]

        # from django.contrib.auth import authenticate
        # 使用用户名密码进行登录
        user = authenticate(username=username, password=password)

        if not user:  # 登录失败
            raise serializers.ValidationError("用户名或者密码不正确......")
        else:  # 登录成功
            # 登录成功之后为用户创建个人资料(给用户设置默认值,使用默认头像)
            UserProfile.objects.get_or_create(
                user=user,
                nick_name=f"GH_{randint(100000, 999999)}",
                head_img="account/static/default/img篮球4.jpg",
            )
            # 登录成功之后为用户创建Token
            Token.objects.get_or_create(user=user)

            attrs["user"] = user
            return attrs


class ResetPasswordSerializer(serializers.Serializer):
    # 一定要登录之后才能修改密码, 所以说肯定是知道user的, 可以不需要username
    new_password = serializers.CharField(required=True, min_length=6)
    confirm_password = serializers.CharField(required=True, min_length=6)

    def validate(self, attrs):
        new_password = attrs["new_password"]
        confirm_password = attrs["confirm_password"]

        if new_password != confirm_password:
            raise serializers.ValidationError("两次输入的密码不一致......")

        else:
            return attrs
